﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Input;
using VideoReflector.Models;
using VideoReflector.Views;
using VideoReflector.Video;

namespace VideoReflector.Controllers
{
    /// <summary>
    /// Controller task with managing clip playback
    /// </summary>
    public class ClipPlayerController : NotifyingObject
    {
        #region Private fields

        private IList<ClipTag> _clipTags;
        private VideoFileType _sessionVideoFile;
        private string _sessionFileDirectory;
        private IClipPlayer _clipPlayer;
        private bool _isFullScreen;

        #endregion Private fields

        #region Constructor

        /// <summary>
        /// Constructor for ClipPlayerController object
        /// </summary>
        /// <param name="clipTags"> Collection of ClipTag objects which correspond to the clips to be exported </param>
        /// <param name="sessionVideo"> Object containing details of video file associated with session </param>
        /// <param name="sessionFileDirectory"> Directory where session files are contained in on disk </param>
        /// <param name="displayContainer"> WPF Panel object to use as container for video display output </param>
        /// <param name="startFullScreen"> Whether to start player in full screen view mode or not (default false) </param>
        public ClipPlayerController(IList<ClipTag> clipTags, VideoFileType sessionVideoFile, string sessionFileDirectory,
                                    System.Windows.Controls.Panel displayContainer, bool startFullScreen = false)
        {
            _clipTags = clipTags;
            _sessionVideoFile = sessionVideoFile;
            _sessionFileDirectory = sessionFileDirectory;
            _clipPlayer = new VlcClipPlayer(clipTags, sessionVideoFile, sessionFileDirectory, displayContainer);
            _isFullScreen = startFullScreen;
        }

        #endregion // Constructor

        #region Public properties

        /// <summary>
        /// Public accessor of ClipPlayer object which exposes bindable properties such as VideoTime
        /// </summary>
        public IClipPlayer ClipPlayer
        {
            get
            {
                return _clipPlayer;
            }
        }

        /// <summary>
        /// Flag for whether player is currently in full screen mode or not
        /// </summary>
        public bool IsFullScreen
        {
            get { return _isFullScreen; }
            set
            {
                _isFullScreen = value;
                NotifyPropertyChanged("IsFullScreen");
            }
        }

        #endregion // Public properties

        #region Commands

        #region Toggle clip playback

        private RelayCommand _toggleClipPlaybackCommand;

        /// <summary>
        /// Toggle clip player between playing and paused states
        /// </summary>
        public ICommand ToggleClipPlaybackCommand
        {
            get
            {
                if (_toggleClipPlaybackCommand == null)
                {
                    _toggleClipPlaybackCommand = new RelayCommand
                    (
                        param => this.ToggleClipPlayback(),
                        param => this.CanToggleClipPlayback()
                    );
                }
                return _toggleClipPlaybackCommand;
            }
        }

        private void ToggleClipPlayback()
        {
            if (ClipPlayer.IsPlaying) 
                { ClipPlayer.Pause(); }
            else 
                { ClipPlayer.Play(); }
        }

        private bool CanToggleClipPlayback()
        {
            return ClipPlayer != null;
        }

        #endregion // Toggle clip playback

        #region Stop clip playback

        private RelayCommand _stopClipPlaybackCommand;

        /// <summary>
        /// Stop clip playback, resetting player
        /// </summary>
        public ICommand StopClipPlaybackCommand
        {
            get
            {
                if (_stopClipPlaybackCommand == null)
                {
                    _stopClipPlaybackCommand = new RelayCommand
                    (
                        param => this.StopClipPlayback(),
                        param => this.CanStopClipPlayback()
                    );
                }
                return _stopClipPlaybackCommand;
            }
        }

        private void StopClipPlayback()
        {
            ClipPlayer.Stop();
        }

        private bool CanStopClipPlayback()
        {
            return ClipPlayer != null && !ClipPlayer.IsStopped;
        }

        #endregion // Toggle clip playback

        #region Skip to next clip

        private RelayCommand _skipToNextClipCommand;

        /// <summary>
        /// Skip to next clip in clip play list
        /// </summary>
        public ICommand SkipToNextClipCommand
        {
            get
            {
                if (_skipToNextClipCommand == null)
                {
                    _skipToNextClipCommand = new RelayCommand
                    (
                        param => this.SkipToNextClip(),
                        param => this.CanSkipToNextClip()
                    );
                }
                return _skipToNextClipCommand;
            }
        }

        private void SkipToNextClip()
        {
            ClipPlayer.SkipToNext();
        }

        private bool CanSkipToNextClip()
        {
            return ClipPlayer != null && ClipPlayer.IsPlaying && ClipPlayer.ClipNumber < _clipTags.Count - 1;
        }

        #endregion // Skip to next clip

        #region Skip to previous clip

        private RelayCommand _skipToPreviousClipCommand;

        /// <summary>
        /// Skip to previous clip in clip play list
        /// </summary>
        public ICommand SkipToPreviousClipCommand
        {
            get
            {
                if (_skipToPreviousClipCommand == null)
                {
                    _skipToPreviousClipCommand = new RelayCommand
                    (
                        param => this.SkipToPreviousClip(),
                        param => this.CanSkipToPreviousClip()
                    );
                }
                return _skipToPreviousClipCommand;
            }
        }

        private void SkipToPreviousClip()
        {
            ClipPlayer.SkipToPrevious();
        }

        private bool CanSkipToPreviousClip()
        {
            return ClipPlayer != null && ClipPlayer.IsPlaying && ClipPlayer.ClipNumber > 0;
        }

        #endregion // Skip to previous clip

        #endregion // Commands

    }
}
